package io.sdph.communication;

import io.sdph.core.ComponentContainer;
import io.sdph.documents.model.InvoiceType;
import io.sdph.documents.model.PaymentMethod;
import io.sdph.order.exceptions.OrderException;
import io.sdph.products.exceptions.ProductException;
import io.sdph.userprofile.exceptions.UserProfileException;
import io.sdph.userprofile.model.Address;
import io.sdph.userprofile.model.UserPermission;
import io.sdph.userprofile.model.UserType;
import io.sdph.ws.Invoice;
import io.sdph.ws.MapProducts;
import io.sdph.ws.MapProperties;
import io.sdph.ws.ObjectFactory;
import io.sdph.ws.Order;
import io.sdph.ws.Product;
import io.sdph.ws.Product.Pictures;
import io.sdph.ws.Return;
import io.sdph.ws.SDPH;
import io.sdph.ws.User;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebParam.Mode;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.Holder;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;


@WebService
public class SDPHServices implements SDPH{
	
	private static ObjectFactory objectFactory = new ObjectFactory();
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "logIn", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.LogIn")
	@ResponseWrapper(localName = "logInRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.LogInRes")
	public Return logIn(
			@WebParam(name = "login", targetNamespace = "http://sdph.pl") String login,
			@WebParam(name = "password", targetNamespace = "http://sdph.pl") String password) {
		// TODO Auto-generated method stub
		ComponentContainer.getInstance().getSessionManager().logIn(login, password);
		Return r = new Return();

		if(ComponentContainer.getInstance().getSessionManager().getCurrentUser() != null) {
			r.setErrorCode("0");
			r.setErrorMessage("OK");
		} else {
			r.setErrorCode("90");
			r.setErrorMessage("Faild.");
		}
		return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "logOut", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.LogOut")
	@ResponseWrapper(localName = "logOutRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.LogOutRes")
	public Return logOut(
			@WebParam(name = "in", targetNamespace = "http://sdph.pl") Object in,
			@WebParam(name = "out", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<String> out) {
		
		ComponentContainer.getInstance().getSessionManager().logOut();
		Return r = new Return();
		if(ComponentContainer.getInstance().getSessionManager().getCurrentUser() == null) {
			r.setErrorCode("0");
			r.setErrorMessage("OK");
		} else {
			r.setErrorCode("990");
			r.setErrorMessage("Faild.");
		}
		
		return r;
	}
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getCurrentUser", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetCurrentUser")
	@ResponseWrapper(localName = "getCurrentUserRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetCurrentUserRes")
	public Return getCurrentUser(
			@WebParam(name = "in", targetNamespace = "http://sdph.pl") Object in,
			@WebParam(name = "user", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<User> user) {
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		try {
		user.value = userToUser(ComponentContainer.getInstance().getSessionManager().getCurrentUser());
		} catch(Exception e) {
			r.setErrorCode("990");
			r.setErrorMessage("Faild.");
		}
		return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "addUser", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.AddUser")
	@ResponseWrapper(localName = "addUserRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.AddUserRes")
	public Return addUser(
			@WebParam(name = "user", targetNamespace = "http://sdph.pl") User user,
			@WebParam(name = "password", targetNamespace = "http://sdph.pl") String password)  {
		// TODO Auto-generated method stub
		
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
	try {
		ComponentContainer.getInstance().getUserManager().addUser(userToUser(user), password);
	} catch (UserProfileException e) {
		// TODO Auto-generated catch block
		r.setErrorMessage(e.getMessage());
		r.setErrorCode("91");
	}
		
		return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "modifyUser", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.ModifyUser")
	@ResponseWrapper(localName = "modifyUserRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.ModifyUserRes")
	public Return modifyUser(
			@WebParam(name = "user", targetNamespace = "http://sdph.pl") User user,
			@WebParam(name = "password", targetNamespace = "http://sdph.pl") String password) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
	try {
		ComponentContainer.getInstance().getUserManager().modifyUser(userToUser(user), password);
	} catch (UserProfileException e) {
		// TODO Auto-generated catch block
		r.setErrorMessage(e.getMessage());
		r.setErrorCode("92");
	}
		
		return r;
	}
	
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "deleteUser", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.DeleteUser")
	@ResponseWrapper(localName = "deleteUserRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.DeleteUserRes")
	public Return deleteUser(
			@WebParam(name = "user", targetNamespace = "http://sdph.pl") User user) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
	try {
		ComponentContainer.getInstance().getUserManager().deleteUser(userToUser(user));
	} catch (UserProfileException e) {
		// TODO Auto-generated catch block
		r.setErrorMessage(e.getMessage());
		r.setErrorCode("93");
	}
		
		return r;
	}
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getUser", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUser")
	@ResponseWrapper(localName = "getUserRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUserRes")
	public Return getUser(
			@WebParam(name = "userId", targetNamespace = "http://sdph.pl") String userId,
			@WebParam(name = "user", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<User> user) {
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
	User u = null;
    try {
		u = userToUser(ComponentContainer.getInstance().getUserManager().getUser(userId));
		user.value = u;
	} catch (UserProfileException e) {
		// TODO Auto-generated catch block
		r.setErrorMessage(e.getMessage());
		r.setErrorCode("990");
	}
     return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getUsers", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUsers")
	@ResponseWrapper(localName = "getUsersRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUsersRes")
	public Return getUsers(
			@WebParam(name = "user", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<List<User>> user) {
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		List<User> users = new ArrayList<User>();
		try {
			for(io.sdph.userprofile.model.User u: ComponentContainer.getInstance().getUserManager().getUsers())
			{
				users.add(userToUser(u));
			}
			user.value = users;
		} catch (UserProfileException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("990");
		}
		return r;
	}
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "makeOrder", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.MakeOrder")
	@ResponseWrapper(localName = "makeOrderRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.MakeOrderRes")
	public Return makeOrder(
			@WebParam(name = "products", targetNamespace = "http://sdph.pl") List<MapProducts> products,
			@WebParam(name = "properties", targetNamespace = "http://sdph.pl") List<MapProperties> properties,
			@WebParam(name = "invoice", targetNamespace = "http://sdph.pl") Invoice invoice,
			@WebParam(name = "order", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<Order> order) {
		io.sdph.order.model.Order o = null;
		
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
		try {
			o = ComponentContainer.getInstance().getOrderManager().order(mapperProducts(products), mapperProperties(properties), invoiceToInvoice(invoice));
			order.value = orderToOrder(o);
		} catch (OrderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("990");
		}
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "cancelOrder", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.CancelOrder")
	@ResponseWrapper(localName = "cancelOrderRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.CancelOrderRes")
	public Return cancelOrder(
			@WebParam(name = "order", targetNamespace = "http://sdph.pl") Order order) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
		try {
			ComponentContainer.getInstance().getOrderManager().cancelOrder(orderToOrder(order));
		} catch (OrderException e) {
			// TODO Auto-generated catch block
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("96");
		}
		return r;
	}
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getUserOrders", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUserOrders")
	@ResponseWrapper(localName = "getUserOrdersRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUserOrdersRes")
	public Return getUserOrders(
			@WebParam(name = "user", targetNamespace = "http://sdph.pl") User user,
			@WebParam(name = "order", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<List<Order>> order) {
		List<Order> o = new ArrayList<Order>();
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
		try {
			for(io.sdph.order.model.Order a: ComponentContainer.getInstance().getOrderManager().getUserOrders(userToUser(user)))
			{
				o.add(orderToOrder(a));
			}
			order.value = o;
		} catch (OrderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("990");
		}
		
		return r;
	}


	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getUserOrderHistory", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUserOrderHistory")
	@ResponseWrapper(localName = "getUserOrderHistoryRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetUserOrderHistoryRes")
	public Return getUserOrderHistory(
			@WebParam(name = "user", targetNamespace = "http://sdph.pl") User user,
			@WebParam(name = "dateFrom", targetNamespace = "http://sdph.pl") XMLGregorianCalendar dateFrom,
			@WebParam(name = "dateTo", targetNamespace = "http://sdph.pl") XMLGregorianCalendar dateTo,
			@WebParam(name = "order", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<List<Order>> order) {
		List<Order> o = new ArrayList<Order>();
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		try {
			for(io.sdph.order.model.Order a: ComponentContainer.getInstance().getOrderManager().getUserOrderHistory(userToUser(user), dateFrom.toGregorianCalendar().getTime(), dateTo.toGregorianCalendar().getTime()))
			{
				o.add(orderToOrder(a));
			}
			order.value = o;
		} catch (OrderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("990");
		}
		
		return r;
	}
	

	@Override
	@WebMethod
	@RequestWrapper(localName = "fill", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.Fill")
	@ResponseWrapper(localName = "fillRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.FillRes")
	public Return fill(
			@WebParam(name = "order", targetNamespace = "http://sdph.pl") Order order) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		try {
			ComponentContainer.getInstance().getOrderManager().fill(orderToOrder(order));
		} catch (OrderException e) {
			// TODO Auto-generated catch block
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("97");
		}
	
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "addProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.AddProduct")
	@ResponseWrapper(localName = "addProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.AddProductRes")
	public Return addProduct(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product,
			@WebParam(name = "quantity", targetNamespace = "http://sdph.pl") long quantity) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		ComponentContainer.getInstance().getMagazineManager().addProduct(productToProduct(product), quantity);
		
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "removeProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.RemoveProduct")
	@ResponseWrapper(localName = "removeProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.RemoveProductRes")
	public Return removeProduct(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product,
			@WebParam(name = "quantity", targetNamespace = "http://sdph.pl") long quantity) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		ComponentContainer.getInstance().getMagazineManager().removeProduct(productToProduct(product), quantity);
		
		
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "setQuantityOfProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.SetQuantityOfProduct")
	@ResponseWrapper(localName = "setQuantityOfProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.SetQuantityOfProductRes")
	public Return setQuantityOfProduct(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product,
			@WebParam(name = "quantity", targetNamespace = "http://sdph.pl") long quantity) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		ComponentContainer.getInstance().getMagazineManager().setQuantityOfProduct(productToProduct(product), quantity);
		return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getQuantityOfProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetQuantityOfProduct")
	@ResponseWrapper(localName = "getQuantityOfProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetQuantityOfProductRes")
	public Return getQuantityOfProduct(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product,
			@WebParam(name = "quantity", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<Long> quantity) {
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
		try {
			quantity.value = ComponentContainer.getInstance().getMagazineManager().getQuantityOfProduct(productToProduct(product));
		} catch(Exception e){
			r.setErrorCode("990");
			r.setErrorMessage(e.getMessage());
		}
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "addProductP", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.AddProductP")
	@ResponseWrapper(localName = "addProductPRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.AddProductPRes")
	public Return addProductP(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		try {
			ComponentContainer.getInstance().getProductManager().addProduct(productToProduct(product));
		} catch (ProductException e) {
			// TODO Auto-generated catch block
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("98");
		}
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "modifyProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.ModifyProduct")
	@ResponseWrapper(localName = "modifyProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.ModifyProductRes")
	public Return modifyProduct(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product) {
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		try {
			ComponentContainer.getInstance().getProductManager().modifyProduct(productToProduct(product));
		} catch (ProductException e) {
			// TODO Auto-generated catch block
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("99");
		}
		return r;
	}

	@Override
	@WebMethod
	@RequestWrapper(localName = "deleteProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.DeleteProduct")
	@ResponseWrapper(localName = "deleteProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.DeleteProductRes")
	public Return deleteProduct(
			@WebParam(name = "product", targetNamespace = "http://sdph.pl") Product product) {	
		// TODO Auto-generated method stub
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		try {
			ComponentContainer.getInstance().getProductManager().deleteProduct(productToProduct(product));
		} catch (ProductException e) {
			// TODO Auto-generated catch block
			r.setErrorMessage(e.getMessage());
			r.setErrorCode("100");
		}
		
		return r;
	}
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getProduct", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProduct")
	@ResponseWrapper(localName = "getProductRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProductRes")
	public Return getProduct(
			@WebParam(name = "id", targetNamespace = "http://sdph.pl") String id,
			@WebParam(name = "product", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<Product> product) {
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		Product p = new Product();
		try {
			p = productToProduct(ComponentContainer.getInstance().getProductManager().getProduct(id));
			product.value = p;
		} catch (ProductException e) {
			r.setErrorCode("990");
			r.setErrorMessage(e.getMessage());
		}
		return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getProducts", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProducts")
	@ResponseWrapper(localName = "getProductsRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProductsRes")
	public Return getProducts(
			@WebParam(name = "limitFrom", targetNamespace = "http://sdph.pl") Long limitFrom,
			@WebParam(name = "limitTo", targetNamespace = "http://sdph.pl") Long limitTo,
			@WebParam(name = "product", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<List<Product>> product) {
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		List<Product> p = new ArrayList<Product>();
		
		try {
			for(io.sdph.products.model.Product a: ComponentContainer.getInstance().getProductManager().getProducts(limitFrom, limitTo))
			{
				p.add(productToProduct(a));
			}
			product.value = p;
		} catch (ProductException e) {
			r.setErrorCode("990");
			r.setErrorMessage(e.getMessage());
		}
		return r;
	}

	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getProductsByName", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProductsByName")
	@ResponseWrapper(localName = "getProductsByNameRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProductsByNameRes")
	public Return getProductsByName(
			@WebParam(name = "name", targetNamespace = "http://sdph.pl") String name,
			@WebParam(name = "limitFrom", targetNamespace = "http://sdph.pl") Long limitFrom,
			@WebParam(name = "limitTo", targetNamespace = "http://sdph.pl") Long limitTo,
			@WebParam(name = "product", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<List<Product>> product) {
		List<Product> p = new ArrayList<Product>();
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
		try {
			for(io.sdph.products.model.Product a: ComponentContainer.getInstance().getProductManager().getProductsByName(name, limitFrom, limitTo))
			{
				p.add(productToProduct(a));
			}
			product.value = p;
		} catch (ProductException e) {
			r.setErrorCode("990");
			r.setErrorMessage(e.getMessage());
		}
		return r;
	}
	
	@Override
	@WebMethod
	@WebResult(targetNamespace = "http://sdph.pl")
	@RequestWrapper(localName = "getProductsByCategory", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProductsByCategory")
	@ResponseWrapper(localName = "getProductsByCategoryRes", targetNamespace = "http://sdph.pl", className = "io.sdph.ws.GetProductsByCategoryRes")
	public Return getProductsByCategory(
			@WebParam(name = "categoryName", targetNamespace = "http://sdph.pl") String categoryName,
			@WebParam(name = "limitFrom", targetNamespace = "http://sdph.pl") long limitFrom,
			@WebParam(name = "limitTo", targetNamespace = "http://sdph.pl") long limitTo,
			@WebParam(name = "product", targetNamespace = "http://sdph.pl", mode = Mode.OUT) Holder<List<Product>> product) {
		List<Product> p = new ArrayList<Product>();
		Return r = new Return();
		r.setErrorCode("0");
		r.setErrorMessage("OK");
		
		try {
			for(io.sdph.products.model.Product a: ComponentContainer.getInstance().getProductManager().getProductsByCategory(categoryName, limitFrom, limitTo))
			{
				p.add(productToProduct(a));
			}
			product.value = p;
		} catch (ProductException e) {
			r.setErrorCode("990");
			r.setErrorMessage(e.getMessage());
		}
		return r;
	}
	
	private io.sdph.userprofile.model.User userToUser(User u)
	{
		Address a = new Address();
		a.setCity(u.getAddress().getCity());
		a.setFlatNo(u.getAddress().getFlatNo());
		a.setHouseNo(u.getAddress().getHouseNo());
		a.setPostalCode(u.getAddress().getPostalCode());
		a.setStreet(u.getAddress().getStreet());
		
		List<UserPermission> p = new ArrayList<UserPermission>();
		
		for(UserPermission per: UserPermission.values())
		{
			for(io.sdph.ws.UserPermission per1 : u.getPermissions())
			{
				if(per.getName().equals(per1.value().toUpperCase()))
						{
							p.add(per);
						}
			}
		}
		
		
		io.sdph.userprofile.model.User user = new io.sdph.userprofile.model.User(u.getId(),
				u.getLogin(),
				u.getUserName(),
				u.getFirstName(), 
				u.getLastName(), 
				u.getLicenseNumber(), 
				null, 
				p,
				a,
				u.getNip(), 
				u.getRegon());
		
		for(UserType ut : UserType.values())
		{
			if(ut.getName().equals(u.getUserType().value().toUpperCase()))
			{
				user.setUserType(ut);
			}
		}
		
		
		return user;
	}
	
	private User userToUser(io.sdph.userprofile.model.User u)
	{
		io.sdph.ws.Address a = new io.sdph.ws.Address();
		a.setCity(u.getAddress().getCity());
		a.setFlatNo(u.getAddress().getFlatNo());
		a.setHouseNo(u.getAddress().getHouseNo());
		a.setPostalCode(u.getAddress().getPostalCode());
		a.setStreet(u.getAddress().getStreet());
		
		List<io.sdph.ws.UserPermission> p = new ArrayList<io.sdph.ws.UserPermission>();
		
		for(io.sdph.ws.UserPermission per: io.sdph.ws.UserPermission.values())
		{
			for(UserPermission per1 : u.getPermissions())
			{
				if(per1.getName().equals(per.value().toUpperCase()))
						{
							p.add(per);
						}
			}
		}
		
		
		User user = new User();
				user.setId(u.getId());
				user.setLogin(u.getLogin());
				user.setUserName(u.getUserName());
				user.setFirstName(u.getFirstName()); 
				user.setLastName(u.getLastName()); 
				user.setLicenseNumber(u.getLicenseNumber()); 				
				user.setAddress(a);
				user.setNip(u.getNip()); 
				user.setRegon(u.getRegon());
				
				for(io.sdph.ws.UserType ut : io.sdph.ws.UserType.values())
				{
					if(u.getUserType().getName().equals(ut.value().toUpperCase()))
					{
						user.setUserType(ut);
					}
				}
				
		return user;
	}
	
	private io.sdph.documents.model.Invoice invoiceToInvoice(Invoice invoice)
	{
		io.sdph.documents.model.Invoice i = new io.sdph.documents.model.Invoice(null);
		
		i.setBuyer(userToUser(invoice.getBuyer()));
		i.setCreationDate(invoice.getCreationDate().toGregorianCalendar().getTime());
		i.setDeadlineDate(invoice.getDeadlineDate().toGregorianCalendar().getTime());		
		i.setPrice(invoice.getPrice());
		i.setProducts(mapperProducts(invoice.getProducts()));
		i.setSellDate(invoice.getSellDate().toGregorianCalendar().getTime());
		
		for(PaymentMethod pm: PaymentMethod.values())
		{
			if(pm.getName().equals(invoice.getPaymentMethod().value()))
				{
				    i.setPaymentMethod(pm);
				}
		}
		
		for(InvoiceType it: InvoiceType.values())
		{
			if(it.getName().equals(invoice.getType().value()))
					{
						i.setType(it);
					}
		}
		
		
		return i;
		
	}
	
	private Invoice invoiceToInvoice(io.sdph.documents.model.Invoice invoice)
	{
		Invoice i = new Invoice();
		
		
		i.setBuyer(userToUser(invoice.getBuyer()));
		i.setCreationDate(null);
		i.setDeadlineDate(null);
		i.setPrice(invoice.getPrice());
		i.setSellDate(null);
		
		GregorianCalendar cd = new GregorianCalendar();
		cd.setTime(invoice.getCreationDate());
		GregorianCalendar dd = new GregorianCalendar();
		dd.setTime(invoice.getDeadlineDate());
		GregorianCalendar sd = new GregorianCalendar();
		sd.setTime(invoice.getSellDate());
		
		try {
			DatatypeFactory df = DatatypeFactory.newInstance();
			i.setCreationDate(df.newXMLGregorianCalendar(cd));
			i.setDeadlineDate(df.newXMLGregorianCalendar(dd));
			i.setSellDate(df.newXMLGregorianCalendar(sd));
			
		} catch (DatatypeConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
		for(io.sdph.ws.PaymentMethod pm: io.sdph.ws.PaymentMethod.values())
		{
			if(pm.value().equals(invoice.getPaymentMethod().getName()))
				{
				    i.setPaymentMethod(pm);
				}
		}
		
		for(io.sdph.ws.InvoiceType it: io.sdph.ws.InvoiceType.values())
		{
			if(it.value().equals(invoice.getType().getName()))
					{
						i.setType(it);
					}
		}
		
		
		return i;
		
	}
	
	private io.sdph.products.model.Product productToProduct(Product product)
	{
		io.sdph.products.model.Product p = new io.sdph.products.model.Product(product.getId());
		
		p.setCategory(product.getCategory());
		p.setDescription(product.getDescription());
		p.setDetails(mapperProperties(product.getDetails()));
		p.setName(product.getName());
		p.setPictures(product.getPictures().getPicture());
		p.setPrice(product.getPrice());
		
		return p;
		
	}
	
	
	private Product productToProduct(io.sdph.products.model.Product product)
	{
		Product p = new Product();
		
		p.setId(product.getId());
		p.setCategory(product.getCategory());
		p.setDescription(product.getDescription());
		p.setName(product.getName());
		p.setPictures(new Pictures());
		p.getPictures().getPicture().addAll(product.getPictures());
		p.setPrice(product.getPrice());
		
		p.getDetails().clear();
		for(MapProperties a: mapperProperties(product.getDetails()))
		{
			p.getDetails().add(a);
		}
		
		return p;
	}
	
	private io.sdph.order.model.Order orderToOrder(Order order)
	{
		io.sdph.order.model.Order o = new io.sdph.order.model.Order(order.getNumber());
		
		o.setInvoice(invoiceToInvoice(order.getInvoice()));
		o.setProducts(mapperProducts(order.getProducts()));
		o.setProperties(mapperProperties(order.getProperties()));
		
		return o;
		
	}
	
	private Order orderToOrder(io.sdph.order.model.Order order)
	{
		Order o = new Order();
		
		o.setNumber(order.getNumber());
		o.setInvoice(invoiceToInvoice(order.getInvoice()));
		o.getProducts().clear();
		for(MapProducts a: mapperProducts(order.getProducts()))
		{
			o.getProducts().add(a);
		}
		
		o.getProperties().clear();
		for(MapProperties a: mapperProperties(order.getProperties()))
		{
			o.getProperties().add(a);
		}
		
		return o;
		
	}
	
	private Map<io.sdph.products.model.Product, Long> mapperProducts(List<MapProducts> products)
	{
		Map<io.sdph.products.model.Product, Long> p = new HashMap<io.sdph.products.model.Product, Long>();
		
		for(MapProducts a: products)
		{
			p.put(productToProduct(a.getKey()),a.getValue());
		}
		
		return p;
	}
	
	private List<MapProducts> mapperProducts(Map<io.sdph.products.model.Product, Long> products)
	{
		List<MapProducts> p = new ArrayList<MapProducts>();
		
		for(Map.Entry<io.sdph.products.model.Product, Long> a : products.entrySet())
		{
			p.add(new MapProducts());
			p.get(p.size()-1).setKey(productToProduct(a.getKey()));
			p.get(p.size()-1).setValue(a.getValue());
		}
		return p;
	}
	
	private Map<String, String> mapperProperties(List<MapProperties> properties)
	{
		Map<String, String> p = new HashMap<String, String>();
		
		for(MapProperties a: properties)
		{
			p.put(a.getKey(), a.getValue());
		}
		return p;
	}
	
	private List<MapProperties> mapperProperties(Map<String, String> properties)
	{
		List<MapProperties> p = new ArrayList<MapProperties>();
		
		for(Map.Entry<String, String> a: properties.entrySet())
		{
			p.add(new MapProperties());
			p.get(p.size()-1).setKey(a.getKey());
			p.get(p.size()-1).setValue(a.getValue());
		}
		
		return p;
	}
	



}
